package com.ruoyi.bluebera.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.bluebera.domain.BizOrders;
import com.ruoyi.bluebera.domain.BizTxRecord;
import com.ruoyi.bluebera.domain.BizTxScanLogs;
import com.ruoyi.bluebera.domain.BizUsers;
import com.ruoyi.bluebera.service.IBizOrdersService;
import com.ruoyi.bluebera.service.IBizTxRecordService;
import com.ruoyi.bluebera.service.IBizTxScanLogsService;
import com.ruoyi.bluebera.service.IBizUsersService;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component("ArbUsdtTxFetcher")

public class ArbUsdtTxFetcher {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            //.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 10080))) // 本地 HTTP 代理
            .build();

    @Autowired
    private IBizOrdersService bizOrdersService;
    @Autowired
    private IBizTxScanLogsService bizTxScanLogsService;
    @Autowired
    private IBizTxRecordService bizTxRecordService;
    @Autowired
    private IBizUsersService bizUsersService;

    public void checkUsdtStatus(){
        BizUsers bizUsers = new BizUsers();
        bizUsers.setValid(0);
        List<BizUsers> list = bizUsersService.selectBizUsersList(bizUsers);
        for (BizUsers each : list) {
            checkUsdtStatus(each.getWalletAddress());
        }
    }


    @Transactional
    public void checkUsdtStatus(String receiveUsdtArbAddress){

        // scan  tx
        try {
            List<BizTxRecord> records = fetchTokenTxList(
                    TaskConstants.ARB_CHAINId,
                    receiveUsdtArbAddress,
                    TaskConstants.USDT_ARB_ADDRESS,
                    TaskConstants.BERA_OFFSET
            );
            for (BizTxRecord record : records) {
                BizTxRecord tx = new BizTxRecord();
                tx.setHash(record.getHash());
                if(bizTxRecordService.selectBizTxRecordList(tx).size()==0) {
                    bizTxRecordService.insertBizTxRecord(record);
                }
            }
        } catch (IOException e) {
            System.err.println("Failed to fetch transactions: " + e.getMessage());
        }

        // 1. get all preprocessing
        BizOrders bizOrders = new BizOrders();
        bizOrders.setTxStatus(TaskConstants.STATUS_PROCESSING);
        bizOrders.setNetwork(TaskConstants.ARB_CHAINId);
        List<BizOrders> list = bizOrdersService.selectBizOrdersList(bizOrders);
        // 2. process according token
        for (BizOrders order : list) {

            BizTxRecord txRecord = new BizTxRecord();
            txRecord.setHash(order.getTxHash());
            txRecord.setChainId(TaskConstants.ARB_CHAINId);
            // change order status and txstatus
            List<BizTxRecord> txRecordList = bizTxRecordService.selectBizTxRecordList(txRecord);
            for(BizTxRecord item : txRecordList) {
                if (item.getConfirmations()>TaskConstants.CONFIRM_COUNT) {
                    // add content to tx log
                    BizTxScanLogs bizTxScanLogs = new BizTxScanLogs();
                /*
                amount DECIMAL(36, 18) default NULL COMMENT '数量',
                bluebera_amount DECIMAL(36, 18) default NULL COMMENT '兑换的bluebera数量',
                rate_to_bluebera DECIMAL(18, 8) default NULL COMMENT '兑换bluebera汇率',
                 */
                    bizTxScanLogs.setOrderId(order.getId());
                    bizTxScanLogs.setPaymentAddress(item.getFromAddr()); // from block
                    bizTxScanLogs.setTxHash(order.getTxHash());
                    bizTxScanLogs.setTokenSymbol(order.getTokenSymbol());
                    bizTxScanLogs.setNetwork(order.getNetwork());

                    bizTxScanLogs.setAmount(item.getValue());  // from block
                    bizTxScanLogs.setBlueberaAmount(item.getValue().divide(new BigDecimal("0.02")));
                    bizTxScanLogs.setRateToBluebera(new BigDecimal("0.02"));
                    bizTxScanLogs.setScannedAt(new Date());
                    bizTxScanLogs.setScanStatus(TaskConstants.STATUS_COMPLETED);
                    bizTxScanLogsService.insertBizTxScanLogs(bizTxScanLogs);

                    // update order
                    order.setTxStatus(TaskConstants.STATUS_COMPLETED);
                    order.setStatus(TaskConstants.STATUS_COMPLETED);
                    bizOrdersService.updateBizOrders(order);
                    logger.warn("arb-usdt updated order={}", order);
                }
            }
        }

    }

    public static List<BizTxRecord> fetchTokenTxList(String chainId, String address, String contractAddress, int offset) throws IOException {
        List<BizTxRecord> records = new ArrayList<>();

        HttpUrl url = HttpUrl.parse(TaskConstants.BASE_URL).newBuilder()
                .addQueryParameter("chainid", chainId)
                .addQueryParameter("module", "account")
                .addQueryParameter("action", "tokentx")
                .addQueryParameter("contractaddress", contractAddress)
                .addQueryParameter("address", address)
                .addQueryParameter("page", "1")
                .addQueryParameter("offset", String.valueOf(offset))
                .addQueryParameter("sort", "desc")
                .addQueryParameter("apikey", TaskConstants.API_KEY)
                .build();

        Request request = new Request.Builder().url(url).get().build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected HTTP response code: " + response.code());
            }

            String body = response.body().string();
            JSONObject json = JSON.parseObject(body);

            if (!"1".equals(json.getString("status"))) {
                throw new IOException("API Error: " + json.getString("message"));
            }

            JSONArray result = json.getJSONArray("result");
            for (int i = 0; i < result.size(); i++) {
                JSONObject tx = result.getJSONObject(i);
                String receiverAddr = tx.getString("to");
                if(receiverAddr.equalsIgnoreCase(address)) {
                    BizTxRecord record = new BizTxRecord();

                    record.setChainId(chainId);
                    record.setBlockNumber(tx.getLong("blockNumber"));
                    record.setBlockTime(new Date(tx.getLong("timeStamp") * 1000));
                    record.setHash(tx.getString("hash"));
                    record.setFromAddr(tx.getString("from"));
                    record.setToAddr(tx.getString("to"));
                    record.setConfirmations(tx.getLong("confirmations"));

                    // 处理 tokenDecimal 和 value
                    String rawValue = tx.getString("value");
                    int decimals = tx.getIntValue("tokenDecimal");
                    BigDecimal divisor = BigDecimal.TEN.pow(decimals);
                    BigDecimal value = new BigDecimal(rawValue).divide(divisor);
                    record.setValue(value);

                    records.add(record);
                }
            }
        }

        return records;
    }

    // 示例主方法
    public static void main(String[] args) {
        try {
            List<BizTxRecord> records = fetchTokenTxList(
                    "42161",
                    "0x8B72b69ACb26cB7Bf0945306502150ebB99D6767",
                    "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
                    10
            );

            for (BizTxRecord r : records) {
                System.out.println(r);
            }
        } catch (IOException e) {
            System.err.println("Failed to fetch token tx list: " + e.getMessage());
        }
    }
}
